package pers.baiban.sqltoword.util;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.stereotype.Component;
import pers.baiban.sqltoword.config.GenConfig;
import pers.baiban.sqltoword.service.TablesService;
import pers.baiban.sqltoword.vo.TableVO;

import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 生成器工具
 *
 * @author 强子初
 * @since 2023/11/30
 */
@Slf4j
@Component
public class GenerateUtil {

    @Autowired
    private TablesService tablesService;

    @Autowired
    private ConversionService convert;

    @Autowired
    private GenConfig genConfig;

    public void generate() {
        List<TableVO> data = loadData();
        XWPFDocument doc = convert.convert(data, XWPFDocument.class);
        except(doc);
    }

    /**
     * 加载数据
     */
    private List<TableVO> loadData() {
        List<TableVO> tables = tablesService.listFullTables()
                .stream()
                // 过滤掉排除表名
                .filter(it -> getExcludeTableNamePredicate().test(it.getTableName()))
                .map(it -> convert.convert(it, TableVO.class))
                .collect(Collectors.toList());
        for (int i = 0; i < tables.size(); i++) {
            tables.get(i).setNumber(i + 1);
        }
        return tables;
    }

    /**
     * 导出
     */
    private void except(XWPFDocument doc) {
        File file = new File(genConfig.getGenName());
        if(!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        try (FileOutputStream out = new FileOutputStream(file, false)) {
            doc.write(out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            log.info("文件生成在：{}", genConfig.getGenName());
        }
    }

    private static Predicate<String> EXCLUDE_TABLE_NAME_PREDICATE = null;

    /**
     * 排除表名后缀处理器
     */
    private Predicate<String> getExcludeTableNamePredicate() {
        if (ObjectUtil.isNotNull(EXCLUDE_TABLE_NAME_PREDICATE))
            return EXCLUDE_TABLE_NAME_PREDICATE;
        EXCLUDE_TABLE_NAME_PREDICATE = new Predicate<String>() {
            @Override
            public boolean test(String name) {
                for (String excludeName : genConfig.getExcludeTableName()) {
                    // 范围处理器
                    if (excludeName.endsWith("*") && name.startsWith(excludeName.substring(0, excludeName.length() - 1))) {
                        return false;
                    }
                    // 都不匹配就是全部匹配
                    if (StrUtil.equals(excludeName, name))
                        return false;
                }
                return true;
            }
        };
        return EXCLUDE_TABLE_NAME_PREDICATE;
    }
}